home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / TPTUTR~1.ZIP / PASCAL17.TXT < prev    next >
Text File  |  1996-03-21  |  13KB  |  367 lines

  1.                         Turbo Pascal for DOS Tutorial
  2.                             by Glenn Grotzinger
  3.                      Part 17: Primary Concepts of Pointers
  4.                    copyright(c) 1995-96 by Glenn Grotzinger
  5.  
  6. Hello.  Here is a solution from last time...
  7.  
  8. program part16;
  9.  
  10.   var
  11.     a: array[1..1000] of integer;
  12.     number: integer;
  13.     c, i, j, PIVOT, t: integer;
  14.     found: boolean;
  15.     location: integer;
  16.     outfile: text;
  17.  
  18.   procedure quicksort(L, R: integer);
  19.     { nothing to say we couldn't sort the data, especially with the
  20.       fact that we will be performing 500 search hits on this 1000
  21.       unit array...the overhead of sorting the data will be of good
  22.       benefit in the long run... }
  23.  
  24.     begin
  25.       if L < R then
  26.         begin
  27.           i := L + 1;
  28.           j := R;
  29.           PIVOT := A[L];
  30.  
  31.           repeat
  32.             while a[i] <= PIVOT do inc(i);
  33.             while a[j] > PIVOT do dec(j);
  34.             if i < j then
  35.               begin
  36.                 t := A[i];
  37.                 A[i] := a[j];
  38.                 A[j] := t;
  39.               end;
  40.           until i > j;
  41.  
  42.           a[l] := A[j];
  43.           a[j] := PIVOT;
  44.  
  45.           quicksort(L, j-1);
  46.           quicksort(i, R);
  47.         end;
  48.     end;
  49.  
  50.   procedure bsearch(number, lowend, highend: integer; var location: integer;
  51.                     var found: boolean);
  52.     var
  53.       midpoint: integer;
  54.     begin
  55.       if lowend > highend then
  56.         found := false
  57.       else
  58.         begin
  59.           midpoint := (lowend + highend) div 2;
  60.           if number = a[midpoint] then
  61.             begin
  62.               found := true;
  63.               location := midpoint;
  64.             end
  65.           else if number < a[midpoint] then
  66.             bsearch(number, lowend, midpoint-1, location, found)
  67.           else if number > a[midpoint] then
  68.             bsearch(number, midpoint+1, highend, location, found);
  69.         end;
  70.     end;
  71.  
  72.   begin
  73.     randomize;
  74.     assign(outfile, 'LOCATION.TXT');
  75.     rewrite(outfile);
  76.  
  77.     for c := 1 to 1000 do
  78.       a[c] := random(10000) + 1;
  79.  
  80.     quicksort(1, 1000);
  81.  
  82.     for c := 1 to 500 do
  83.       begin
  84.         number := random(10000) + 1;
  85.         bsearch(number, 1, 1000, location, found);
  86.         if found then
  87.           writeln(outfile, c, ') ', number, ' was found at position ',
  88.                   location, '.');
  89.       end;
  90.  
  91.     close(outfile);
  92.  
  93. end.
  94.  
  95. Intro
  96. =====
  97. This will be the first of several parts on the use of pointers...This
  98. part will contain the basic idea behind pointers and their use.  I
  99. would like feedback from anyone about how well they felt they learned
  100. from this tutorial, and the next two.  They all will be about pointers,
  101. and I want to be sure I am doing OK in explaining them coherently. :>
  102.  
  103. The Concept of a Pointer
  104. ========================
  105. A pointer is simply what it implies by the name.  Something that points.
  106. A pointer is a 4 byte double word that stores the segment and offset in
  107. memory where the variable is located.
  108.  
  109. We have referred to before a method of getting more than 64K in a data
  110. structure, in the array section.  This is a way.  A pointer is placed on
  111. what is referred to as the heap.  The heap is the remainder of conventional
  112. memory not used by the program itself, the data stack, or any TSRs that
  113. may be on the system at any one time.  The data stack is where variables
  114. are normally allocated directly by name and can be a maximum of 64K in size.
  115.  
  116. Why would we want to use pointers?  Well, we have already eluded to one
  117. reason, to get around the 64K data limit.  Another reason is to dynamically
  118. allocate memory space.  Basically, any variables declared by name(s) in a
  119. program is allocated at the initial start-up of a program, and is allocated
  120. until the end of the program.  For a lengthy program with a lot of variables,
  121. we may not want all variables to be allocated for something at the start.
  122. Therefore, we can, with pointers, allocate and deallocate memory anytime
  123. we wish in a program.
  124.  
  125. If we want to save memory in the data stack, 1 4-byte pointer compared to,
  126. say, an array of 1000 integers would be preferable.  That is one function
  127. of a pointer.
  128.  
  129. In using pointers, we must remember that they are not direct variables,
  130. but addresses of variables.  Let us look at the first example program
  131. below to see exactly what I mean by the last statement.  We also will
  132. see how to properly create variable space address pointers in memory,
  133. address that variable space, and then deallocate it.
  134.  
  135. program pointers_one;
  136.  
  137.   type
  138.     strptr = ^string;
  139.   var
  140.     a, b, c: strptr;
  141.  
  142.   begin
  143.     new(a);
  144.     a^ := 'Turbo Pascal';
  145.     new(b);
  146.     b^ := 'is fun!!!!!!';
  147.  
  148.     writeln('a is now "', a^, '".');
  149.     writeln('b is now "', b^, '".');
  150.  
  151.     new(c);
  152.     c^ := a^;
  153.     a^ := b^;
  154.     b^ := c^;
  155.     dispose(c);
  156.  
  157.     writeln;
  158.     writeln('a is now "', a^, '".');
  159.     writeln('b is now "', b^, '".');
  160.     dispose(a);dispose(b);
  161.  
  162.   end.
  163.  
  164. We see the use of several use conventions in the program above.  We have
  165. three pointers listed to be pointers of strings.  (as a note, any data
  166. type that will eventually be a pointer should NORMALLY be defined under
  167. the type declaration to facilitate the use of pointers in procedures.
  168. We will see this later.)
  169.  
  170. In the declaration to allocate the pointers, we used the ^ sign first, then
  171. the datatype.  We say that the pointer will eventually point to a string
  172. variable.
  173.  
  174. To address each of the pointer variables, we used the ^ sign after the
  175. particular variable name.  The ^ sign references the variable that the
  176. pointer is pointing to, and NOT the pointer itself.  You may see this
  177. by doing a debug trace for a, b, and c on that program.  You will
  178. clearly see that the pointer's contents is NOT what the variable's
  179. contents is...
  180.  
  181. The next thing to note is the assignment statements.  For a pointer
  182. variable, we are not assigning direct values, but MOVING THE POINTER
  183. address.  When we say a^ := c^, we are moving the pointer c to point
  184. to the value that a points to.  **WE ARE NOT DIRECTLY CHANGING THE
  185. VALUE OF THAT LOCATION IN MEMORY!!!**.
  186.  
  187. The last thing to note is the strategically placed uses of the functions
  188. new() and dispose().  These are new functions to us that we will learn
  189. and make use of in the system unit.  The new() function will allocate
  190. the space for the pointer listed in the variable on the heap.  The
  191. dispose() function will deallocate the space for the pointer on the heap.
  192. As you can see, we created and removed the variables as we needed them.
  193.  
  194. The next thing you were probably wondering with pointers is how to get
  195. a pointer to not point to anything.  Make it address a reserved word
  196. called nil.  If I want pointer p to not point to anything, then I would
  197. write:
  198.  
  199.         p := nil;
  200.  
  201. Whatever you do, do not set a pointer to nil before you dispose of the
  202. pointer.  The system will lose track of the variable on the heap, and
  203. therefore is LOST to the system.  Keep this issue in mind as we do
  204. our work and examples with pointers.
  205.  
  206. Look up getmem() and freemem().
  207.  
  208. Another issue that wasn't covered above is how we determine how much
  209. memory is in the heap.  Use the functions memavail and maxavail for
  210. the purpose of finding out how much memory you can allocate and if the
  211. pointer data structure is big enough, BE SURE TO CHECK AND SEE IF YOU
  212. HAVE THE MEMORY TO ALLOCATE before you allocate it for a big structure.
  213.  
  214. Procedure or Function Pointers
  215. ==============================
  216. A procedure or function may also be addressed as a pointer.  For that,
  217. as you will see in the example, we can use a declaration for a variable
  218. exactly like the procedure or function declaration.  It is very useful
  219. to minimize code usage, and make things multi-functional.  This sheds
  220. some light into the inner workings of the write command, as was wondered
  221. in c.l.p.b. a little while ago...
  222.  
  223. program pointer_two;
  224.   type
  225.     compfunc = function(a, b: integer):integer;
  226.   var
  227.     compute: compfunc;
  228.     first, second: integer;
  229.     choice: char;
  230.  
  231.   {$F+}
  232.   function compadd(a, b: integer): integer;
  233.     begin
  234.       compadd := a + b;
  235.     end;
  236.   function compsub(a, b: integer): integer;
  237.     begin
  238.       compsub := a - b;
  239.     end;
  240.   function compmult(a, b: integer): integer;
  241.     begin
  242.       compmult := a * b;
  243.     end;
  244.   function compdiv(a, b: integer): integer;
  245.     begin
  246.       compdiv := a div b;
  247.     end;
  248.  
  249. {$F-}
  250.  
  251.   begin
  252.     @compute := nil;
  253.     write('Enter a first number: ');
  254.     readln(first);
  255.     write('Enter a second number: ');
  256.     readln(second);
  257.     write('Enter +, -, *, or / as a operation: ');
  258.     readln(choice);
  259.     case choice of
  260.       '+': compute := compadd;
  261.       '-': compute := compsub;
  262.       '*': compute := compmult;
  263.       '/': compute := compdiv;
  264.     else
  265.       writeln('Enter a correct option.');
  266.     end;
  267.     compute(first, second);
  268.     writeln(first, ' ', choice, ' ',second,' = ',compute(first, second));
  269.  
  270.   end.
  271. As you can see, we are assigning a particular function to the function
  272. named compute.  After that, compute performs the specified function of
  273. the function that we just assigned to it.  The rule is that those FAR
  274. declarations MUST be present.  As well, you can see how to refer to the
  275. procedure pointer (as @procedure).  As long as the declarations are
  276. similar for all the functions, we can readdress functions/procedures
  277. using a variable like we did above.
  278.  
  279. We see that we can probably cut down on a lot of code by using this
  280. method if we had several different ways of doing things, with large
  281. amounts of code for each thing.  For example, if we wanted to sort
  282. something based on user input dependent upon many different methods
  283. or types (say sort increasing by name, decreasing by name, increasing
  284. on size, by date, et.al), we can set up our swapping procedure to be
  285. the way the compute procedure is above.
  286.  
  287. Now, we will lead into a special usage of a pointered procedure called
  288. exitproc.
  289.  
  290. ExitProc
  291. ========
  292. This is a special defined procedure pointer in Pascal that will determine
  293. the procedures that will be performed upon an exit, NO MATTER what happens,
  294. EVEN IF THERE IS A RUN-TIME ERROR.  Here is your method on being able to
  295. catch and log those run-time errors either to the screen, or to an errors
  296. log.  The primary usage of an exit procedure, though, is to perform any
  297. maintenance that needs to be done upon termination that may not get done
  298. upon an abnormal termination, such as closing files. The way things work
  299. are basically the same as above...
  300.  
  301. Here is a short example...I will force a run-time error in this program,
  302. so we can see that the end gets run anyway.  As you may see, exitproc
  303. is defined as a pointered procedure when we work with it.  The rest is
  304. basically documented.
  305.  
  306. program pointer_three;
  307.  
  308.   var
  309.     exitsave: procedure;
  310.     afile: text;
  311.  
  312.   {$F+}    { must be far }
  313.   procedure myexit; {must be parameterless}
  314.     begin
  315.       if exitcode <> 0 then
  316.         writeln('There was a problem.');
  317.       writeln('We are exiting...');
  318.     end;
  319.   {$F-}
  320.  
  321.   begin
  322.     @exitsave := exitproc;  { saving the original exit procedure }
  323.     exitproc := @myexit;    { set to new exit procedure }
  324.  
  325.     { I am placing a couple of error situations in here so you can
  326.       experiment with what is going on...try it without errors too! }
  327.  
  328.     {1 - here is a standard file not found RTE.}
  329.     assign(afile, '()()()().!!!');
  330.     reset(afile);
  331.  
  332.     {2 - here is a division by zero.}
  333.     { writeln(3 / 0); }
  334.  
  335.     exitproc := @exitsave;  { set the original exit procedure back }
  336.   end.
  337.  
  338. Here is enough material that I believe that is enough to digest for right
  339. now on use of pointers.  Practice allocating and using pointers very
  340. heavily, as we will get into more advanced issues of using pointers in the
  341. next two parts...Remember that ANY structure can be placed as a pointer,
  342. except for files, and remember to define types for all pointers.
  343.  
  344. Practice Programming Problem #17
  345. ================================
  346. Randomly generate 15000 numbers from 1-25000 into an array.
  347. Then generate another 10000 numbers from 1-25000.
  348. If there is a number from the second set of numbers that happens to be in
  349. the first set of numbers, write out to the file named LOCAT2.TXT something
  350. such as:
  351.  
  352. 13131 was found at position 12000.
  353.  
  354. Only indicate the first instance of the number you encounter.
  355. You may wish to write a "redrawing bar" for a process indicator.
  356.  
  357. Note: Be sure with the allocation for those first 15000 numbers that you
  358. keep in line with the topic of this tutorial.
  359.  
  360. Next Time
  361. =========
  362. We will cover the concept of linked lists, or chained lists.  Practice
  363. very heavily the idea of pointers, because you will need use of them
  364. again in the next section.  E-mail ggrotz@2sprint.net with your comments.
  365.  
  366.  
  367.